import { Component, OnInit, ViewChild, TemplateRef } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { Observable } from 'rxjs'
import { NzMessageService } from 'ng-zorro-antd'
import { STColumn, STColumnBadge } from '@delon/abc'
import { SettingsService } from '@delon/theme'
import { I18NService } from '@core'
import { ListBaseClass } from '@shared/classes/ListBaseClass'
import { ISearchSchema, ISearchOption } from '@shared/interfaces/search'
import { ESearchType, ETransScene, EPaymentBrand } from '@shared/enums'
import { ITradeQueryParams, ITrade } from '@shared/interfaces/trade'
import {
  generatePaymentBrandOptions,
  generateTransSceneOptions,
  openDownloadDialog,
  signAmtNumberOfTrade,
} from 'app/utils/helpers'
import { TradeService } from '../trade-abstract.service'
import { EDateLimitEnum, Currency, IOption } from '@shared/interfaces/common'
import { today, TradeAmountMaxValue } from 'app/utils/contraints'
import { CurrencyService } from '@shared/services/currency.service'
import { AAMSFilterInit } from '@shared/interfaces/aams'
import { I18NPrefixWithPipe } from '@shared/filters/i18n-prefix-with.pipe'
import { Channel } from '@shared/interfaces/channel'
import { ChannelService } from '@shared/services/channel.service'
import { tap } from 'rxjs/operators'

const commonParams = {
  chanCode: '',
  currency: '',
  page: 1,
  size: 10,
  transScene: '',
}

@Component({
  selector: 'app-trades-list',
  templateUrl: './list.component.html',
  styleUrls: ['../../../shared/styles/table.less', './list.component.less'],
})
export class TradesListComponent extends ListBaseClass<ITrade, ITradeQueryParams> implements OnInit, AAMSFilterInit {
  @ViewChild('transAmt') transAmt: TemplateRef<void>
  @ViewChild('insTpl') insTpl: TemplateRef<void>
  @ViewChild('agentTpl') agentTpl: TemplateRef<void>
  @ViewChild('merchantTpl') merchantTpl: TemplateRef<void>
  @ViewChild('storeTpl') storeTpl: TemplateRef<void>
  @ViewChild('tplCurrency') tplCurrency: TemplateRef<void>
  @ViewChild('tplTransScene') tplTransScene: TemplateRef<void>
  @ViewChild('tplChannel') tplChannel: TemplateRef<void>
  // @ViewChild('tplChanMer') tplChanMer: TemplateRef<void>

  TradeAmountMaxValue = TradeAmountMaxValue

  transAmtFrom: number // 交易金额从
  transAmtTo: number // 交易金额到

  selectedCurrency: Currency
  selectedChannelMerchant: Channel

  searchSchema: ISearchSchema[] = []
  customSchema: ISearchSchema[] = []

  procFlagOptions: ISearchOption[] = []

  transSceneOptions: IOption[] = []
  selectedTransScene: ETransScene // 搜索交易场景
  selectedChannel: EPaymentBrand // 搜索渠道
  channelOptions$: Observable<ISearchOption[]>

  data: ITrade[] = []

  currencyList$: Observable<Currency[]>
  insCode: string
  columns: STColumn[] = []

  math = Math // 引用使 html 可以调用

  procBadge: STColumnBadge = {
    5: { text: this.trans('TRADE_STATUS.PENDING'), color: 'processing' },
    2: { text: this.trans('TRADE_STATUS.REJECT'), color: 'error' },
    0: { text: this.trans('TRADE_STATUS.RESOLVE'), color: 'success' },
    '': { text: this.trans('GENERAL.INFO.UNKOWN'), color: 'error' },
  }

  constructor(
    public msg: NzMessageService,
    public i18n: I18NService,
    public router: Router,
    public route: ActivatedRoute,
    public settingService: SettingsService,
    private currencyService: CurrencyService,
    private tradeService: TradeService,
    private i18nPrefixWithPipe: I18NPrefixWithPipe,
    private channelService: ChannelService,
  ) {
    super(msg, i18n, route, router, settingService)
    this.setDefaultParams(commonParams)
  }

  ngOnInit(): void {
    this.initColumns()
    this.getInsCode()
    this.genTransSceneOptions()
    this.initChannelOptions()
    this.initStatusOptions()
    this.initSearchSchema()
    this.handleSearch()
    this.initialAAMSFilter()
  }

  initialAAMSFilter() {
    this.initAcquirer()
    this.initAgent()
    this.initMerchant()
    this.initStore()
  }

  getDecimalByCurrencyCode(currCode: string): Observable<number> {
    return this.currencyService.getDecimalByCode(currCode)
  }

  genTransSceneOptions(): void {
    this.transSceneOptions = generateTransSceneOptions().map(item => {
      item.label = this.i18nPrefixWithPipe.transform(item.value, 'TRANS_SCENE.')
      return item
    })
  }

  initColumns(): void {
    this.columns = [
      {
        type: 'link',
        title: '订单号',
        i18n: 'TRADE.ORDER_NUM',
        index: 'orderNum',
        className: 'text-center',
        width: '150px',
        fixed: 'left',
        click: this.goDetail.bind(this),
      },
      {
        title: '门店名称',
        i18n: 'GENERAL.STORE.NAME',
        index: 'storeName',
        width: '150px',
        className: 'text-center',
      },
      {
        title: '交易时间',
        i18n: 'TRADE.TRANS_TIME',
        index: 'createdAt',
        className: 'text-center',
        type: 'date',
        width: '150px',
        dateFormat: 'YYYY-MM-DD HH:mm',
      },
      {
        title: '交易场景',
        i18n: 'TRADE.TRANS_SCENE',
        className: 'text-center',
        width: '100px',
        render: 'transScene',
      },
      {
        title: '渠道',
        i18n: 'GENERAL.BIZ_LEVEL.CHANNEL',
        className: 'text-center',
        width: '100px',
        render: 'transChannel',
      },
      {
        title: '交易金额',
        i18n: 'TRADE.TRANS_AMT',
        className: 'text-right p-sm',
        width: '100px',
        render: 'transAmt',
      },
      {
        title: '状态',
        i18n: 'GENERAL.INFO.STATUS',
        index: 'procFlag',
        type: 'badge',
        badge: this.procBadge,
        className: 'text-center',
        width: '100px',
        fixed: 'right',
      },
    ]
  }

  getInsCode(): void {
    const { insCode } = this.settingService.user
    this.insCode = insCode
  }

  initStatusOptions(): void {
    for (const key in this.procBadge) {
      const option = { label: this.procBadge[key].text, value: key }
      this.procFlagOptions.push(option)
    }
  }

  initSearchSchema(): void {
    this.searchSchema = this.getSearchSchema()
  }

  getSearchSchema(): ISearchSchema[] {
    return [
      {
        label: 'TRANS_TIME',
        labelI18n: 'TRADE.TRANS_TIME',
        index: ['createdAtFrom', 'createdAtTo'],
        type: ESearchType.dateRange,
        allowClear: false,
        dateLimitType: EDateLimitEnum.Month,
        value: [today, today],
      },
      {
        label: 'ORDER_NUM',
        labelI18n: 'TRADE.ORDER_NUM',
        index: 'orderNum',
        type: ESearchType.input,
        value: '',
      },
      {
        label: 'TRANS_AMT',
        labelI18n: 'TRADE.TRANS_AMT',
        index: ['transAmtFrom', 'transAmtTo'],
        component: this.transAmt,
        customFunc: () => [this.transAmtFrom, this.transAmtTo],
      },
      {
        label: 'TRANSACTION_CURRENCY',
        labelI18n: 'GENERAL.INFO.TRANSACTION_CURRENCY',
        index: 'currency',
        component: this.tplCurrency,
        customFunc: () => (this.selectedCurrency ? this.selectedCurrency.code : ''),
      },
      {
        label: 'CHANNEL',
        labelI18n: 'GENERAL.INFO.CHANNEL',
        index: 'channel',
        component: this.tplChannel,
        customFunc: () => (this.selectedChannel ? this.selectedChannel : '')
      },
      // TODO: 暂时掩藏渠道商户的搜索框
      // {
      //   label: 'Channel Merchant ID',
      //   labelI18n: 'GENERAL.INFO.CHANNEL.MERCHANT',
      //   index: 'chanMerID',
      //   component: this.tplChanMer,
      //   customFunc: () => (this.selectedChannelMerchant ? this.selectedChannelMerchant.chanMerID : ''),
      // },
      {
        label: 'TRANS_SCENE',
        labelI18n: 'TRADE.TRANS_SCENE',
        index: 'transScene',
        component: this.tplTransScene,
        customFunc: () => (this.selectedTransScene ? this.selectedTransScene : ''),
      },
      {
        label: 'GENERAL.INFO.STATUS',
        labelI18n: 'GENERAL.INFO.STATUS',
        index: 'procFlag',
        type: ESearchType.selection,
        options: this.procFlagOptions,
      },
      {
        label: 'INSTITUTION',
        labelI18n: 'GENERAL.BIZ_LEVEL.INSTITUTION',
        index: 'insCode',
        component: this.insTpl,
        customFunc: () => (this.selectedAcquirer ? this.selectedAcquirer.code : ''),
      },
      {
        label: 'AGENT',
        labelI18n: 'GENERAL.BIZ_LEVEL.AGENT',
        index: 'agentCode',
        component: this.agentTpl,
        customFunc: () => (this.selectedGroup ? this.selectedGroup.code : ''),
      },
      {
        label: 'MERCHANT',
        labelI18n: 'GENERAL.BIZ_LEVEL.MERCHANT',
        index: 'intMerCode',
        component: this.merchantTpl,
        customFunc: () => (this.selectedMerchant ? this.selectedMerchant.code : ''),
      },
      {
        label: 'STORE',
        labelI18n: 'GENERAL.BIZ_LEVEL.STORE',
        index: 'intStoreCode',
        component: this.storeTpl,
        customFunc: () => (this.selectedStore ? this.selectedStore.code : ''),
      },
      {
        label: 'TERMINAL',
        labelI18n: 'GENERAL.BIZ_LEVEL.TERMINAL',
        index: 'termCode',
        type: ESearchType.input,
      },
      {
        label: '卡号',
        labelI18n: 'TRADE.CARD_NUMBER',
        index: 'acctNum',
        type: ESearchType.input,
      },
      {
        label: '授权码',
        labelI18n: 'TRADE.AUTH_CODE',
        index: 'authCode',
        type: ESearchType.input,
      },
      {
        label: '检索参考号',
        labelI18n: 'TRADE.RRN',
        index: 'retrievalRefNum',
        type: ESearchType.input,
      },
      {
        label: '交易流水号',
        labelI18n: 'TRADE.SERIALNUM',
        index: 'termTraceNum',
        type: ESearchType.input,
      },
      {
        label: '交易批次号',
        labelI18n: 'TRADE.BATCHNUM',
        index: 'batchNum',
        type: ESearchType.input,
      },
    ]
  }

  initChannelOptions(): void {
    this.channelOptions$ = this.channelService.getCurrentSupportChannelOptions()
  }

  goDetail(record: ITrade): void {
    const { orderNum, intStoreCode, category } = record
    this.router.navigate([`../${orderNum}/${intStoreCode}/${category}`], { relativeTo: this.route })
  }

  queryTableDataWithParams(): void {
    this.loading = true
    this.tradeService.getList(this.params).subscribe(this.renderList.bind(this), this.getListError.bind(this))
  }

  /** 交易金额校验 */
  validateTransAmt() {
    /** 点击搜索也会报错，这里删除所有的报错信息，避免信息过多 */
    this.msg.remove()
    const transAmtFromVal = this.transAmtFrom
    const transAmtToVal = this.transAmtTo

    if (
      (!isNaN(transAmtFromVal) &&
        (transAmtFromVal > Number.MAX_SAFE_INTEGER || transAmtFromVal > TradeAmountMaxValue)) ||
      (!isNaN(transAmtToVal) && (transAmtToVal > Number.MAX_SAFE_INTEGER || transAmtToVal > TradeAmountMaxValue))
    ) {
      this.msg.error(this.trans('VALIDATION.MAX_VALUE', { value: TradeAmountMaxValue }))
      this.searchValid = false
      return
    }

    /** 当 transAmtTo 有值时会做比较，即允许只输一个 */
    if (!isNaN(transAmtFromVal) && !isNaN(transAmtToVal) && !!transAmtToVal && transAmtFromVal > transAmtToVal) {
      this.msg.error(this.trans('TRADE.MIN_AMT_LTE_MAX_AMT'))
      this.searchValid = false
      return
    }

    this.searchValid = true
  }

  checkSearchParamsValidation(): boolean {
    this.validateTransAmt()
    const transAmtFromVal = this.transAmtFrom
    const transAmtToVal = this.transAmtTo

    if (!isNaN(transAmtFromVal) || !isNaN(transAmtToVal)) {
      if (!this.selectedCurrency) {
        this.msg.error(
          this.trans('VALIDATION.REQUIRED_SELECT', { name: this.trans('GENERAL.INFO.TRANSACTION_CURRENCY') }),
        )
        return false
      }
    }
    return this.searchValid
  }

  download(): void {
    this.tradeService.getTradeListReport(this.params).subscribe(data => {
      const { url } = data
      openDownloadDialog(url, '下载报表')
    })
  }

  computeTransAmt(trade: ITrade): number {
    return signAmtNumberOfTrade(trade)
  }
}
